/* ========================================================================== */
/*                                                                            */
/*   usb.h                                                                    */
/*   (c) 2008 Kwong                                                           */
/*                                                                            */
/*   Define USB 2.0 constants and structures                                  */
/*                                                                            */
/* ========================================================================== */
#ifndef _USB_H
#define _USB_H

#include "system.h"

//------------------------------------------------------------------------------
//! \defgroup usb_std_struc USB standard structures
//! \brief Chapter 9 of the USB specification 2.0 (usb_20.pdf) describes a
//!        standard USB device framework. Several structures and associated
//!        constants have been defined on that model and are described here.
//! \see usb_20.pdf - Section 9
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \defgroup usb_api_struct USB API Structures
//! \brief The USB API uses various custom structures to track the state of
//!        the USB controller, endpoints, and the like. These structures are
//!        described here.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \defgroup usb_api_methods USB API Methods
//! \brief  Methods provided by the USB API to manipulate a USB driver.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \defgroup usb_api_callbacks Callback API
//! \brief These callback functions are used by the USB API to notify the
//!        user application of incoming events or actions to perform.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \defgroup usb_std_req_hlr Standard Request Handler
//! \brief This module provides a way to easily handle standard standard
//!        requests.
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//      Definitions
//------------------------------------------------------------------------------

// USB standard definitions
//---------------------------------------------------------
//! \ingroup usb_std_req_hlr
//! \defgroup std_dev_req Standard Device Requests
//! These are the standard request defined for a SETUP transaction. Please refer
//! to Section 9.4 of the USB 2.0 specification (usb_20.pdf) for more
//! information. Table 9.4 defines the bRequest values for each request.
//! \see S_usb_request
//! \see usb_20.pdf - Section 9.4
//! @{

//! \brief  Returns the status for the specified recipient.
//! \see    get_status_const
//! \see    usb_20.pdf - Section 9.4.5
#define USB_GET_STATUS                 0x00

//! \brief  Disables a specific feature of the device
//! \see    usb_20.pdf - Section 9.4.1
//! \see    clr_set_feat_const
#define USB_CLEAR_FEATURE              0x01

// Reserved for futur use              0x02

//! \brief  Enables a specific feature of the device
//! \see    clr_set_feat_const
//! \see    set_feat_const
//! \see    usb_20.pdf - 9.4.9
#define USB_SET_FEATURE                0x03

// Reserved for futur use              0x04

//! \brief  Sets the device address for subsequent accesses
//! \see    usb_20.pdf - Section 9.4.6
#define USB_SET_ADDRESS                0x05

//! \brief  Returns the specified descriptor if it exists
//! \see    usb_20.pdf - Section 9.4.3
#define USB_GET_DESCRIPTOR             0x06

//! \brief  Updates existing descriptors or creates new descriptors
//! \brief  This request is optional
//! \see    usb_20.pdf - Section 9.4.8
#define USB_SET_DESCRIPTOR             0x07

//! \brief  Returns the current configuration value of the device
//! \see    usb_20.pdf - Section 9.4.2
#define USB_GET_CONFIGURATION          0x08

//! \brief  Sets the configuration of the device
//! \see    usb_20.pdf - Section 9.4.7
#define USB_SET_CONFIGURATION          0x09

//! \brief  Returns the specified alternate setting for an interface
//! \see    usb_20.pdf - Section 9.4.4
#define USB_GET_INTERFACE              0x0A

//! \brief  Selects an alternate setting for the selected interface
//! \see    usb_20.pdf - Section 9.4.10
#define USB_SET_INTERFACE              0x0B

//! \brief  Sets and reports an endpoint synchronization frame
//! \see    usb_20.pdf - Section 9.4.11
#define USB_SYNCH_FRAME                0x0C
//! @}

//! \ingroup std_dev_req
//! \defgroup get_set_desc_const Get/Set Descriptor - Constants
//! \brief Useful constants when declaring a Get Descriptor or Set Descriptor
//!        standard request
//! \see StdReq
//! \see S_usb_device_descriptor
//! \see S_usb_configuration_descriptor
//! \see S_usb_endpoint_descriptor
//! \see S_usb_device_qualifier_descriptor
//! \see S_USB_LANGUAGE_ENGLISH_US
//! \see usb_20.pdf - Section 9.5 - Table 9.5
//! @{

//! \name Descriptor Types
//! \brief Possible bDescriptorType values for the descriptor structures.
//!
//! They can be used with Get Descriptor and Set Descriptor standard requests
//! to retrieve/modify them
//! @{

//! \brief Device descriptor
#define USB_DEVICE_DESCRIPTOR                       0x01

//! \brief Configuration descriptor
#define USB_CONFIGURATION_DESCRIPTOR                0x02

//! \brief String descriptor
#define USB_STRING_DESCRIPTOR                       0x03

//! \brief Interface descriptor
#define USB_INTERFACE_DESCRIPTOR                    0x04

//! \brief Endpoint descriptor
#define USB_ENDPOINT_DESCRIPTOR                     0x05

//! \brief Device qualifier descriptor
#define USB_DEVICE_QUALIFIER_DESCRIPTOR             0x06

//! \brief Other speed configuration descriptor
#define USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR    0x07

//! \brief Interface power descriptor
#define USB_INTERFACE_POWER_DESCRIPTOR              0x08

//! \brief otg descriptor
#define USB_OTG_DESCRIPTOR     		    	    0x09

//! \brief debug descriptor
#define USB_DEBUG_DESCRIPTOR   		    	    0x0A

//! \brief Assoication interface descriptor
#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR	    0x0B
//! @}
//! @}

//! \ingroup std_dev_req
//! \defgroup clr_set_feat_const Clear/Set Feature - Constants
//! \brief Useful constants when declaring a Clear Feature or Set Feature
//! standard request.
//! \see std_dev_req
//! \see S_usb_request
//! \see usb_20.pdf - Section 9.4 - Table 9.6
//! @{

//! \name Standard Feature Selectors
//! Possible values for the wValue field of the Clear Feature and Set Feature
//! standard requests.
//! @{

//! \brief Halt feature of an endpoint
#define USB_ENDPOINT_HALT              0x00

//! \brief Remote wake-up feature of the device
#define USB_DEVICE_REMOTE_WAKEUP       0x01

//! \brief USB test mode
#define USB_TEST_MODE                  0x02
//! @}
//! @}

//! \ingroup std_dev_req
//! \defgroup set_feat_const Set Feature - Constants
//! \brief Useful constants when declaring a Set Feature standard request
//! \see usb_20.pdf - Section 7.1.20
//! \see usb_20.pdf - Section 9.2.9 - Table 9.7
//! @{

//! \name Test Mode Selectors
//! \brief Test modes available to probe an USB device.
//! @{

//! \brief Tests the high-output drive level on the D+ line
#define TEST_J                         0x01

//! \brief Tests the high-output drive level on the D- line
#define TEST_K                         0x02

//! \brief Tests the output impedance, low-level output voltage and loading
//!        characteristics
#define TEST_SEO_NAK                   0x03

//! \brief Tests rise and fall times, eye patterns and jitter
#define TEST_PACKET                    0x04

//! \brief Tests the hub disconnect detection
#define TEST_FORCE_ENABLE              0x05
//! @}
//! @}

//! \ingroup usb_std_struc
//! \defgroup ept_desc_const Endpoint Descriptor - Constants
//! \brief Useful constants when declaring an endpoint descriptor
//! \see S_usb_endpoint_descriptor
//! \see usb_20.pdf - Section 9.6.6 - Table 9.13
//! @{

//! \name  bEndpointAddress field
//! \brief Values for the bEndpointAddress field of an endpoint descriptor.
//! @{

//! \brief Defines an OUT endpoint
#define USB_ENDPOINT_OUT                            (0 << 7)

//! \brief Defines an IN endpoint
#define USB_ENDPOINT_IN                             (1 << 7)
//! @}

//! \name  bmAttributes field
//! \brief These are the four possible tranfer type values for the bmAttributes
//!        field of an endpoint descriptor.
//! @{

//! \brief Defines a CONTROL endpoint
#define ENDPOINT_TYPE_CONTROL          0x00

//! \brief Defines a ISOCHRONOUS endpoint
#define ENDPOINT_TYPE_ISOCHRONOUS      0x01

//! \brief Defines a BULK endpoint
#define ENDPOINT_TYPE_BULK             0x02

//! \brief Defines an INTERRUPT endpoint
#define ENDPOINT_TYPE_INTERRUPT        0x03
//! @}
//! @}

//! \name  bmRequestType field
//! \brief This bitmapped field identifies the characteristics of the specific
//!        request.
//! \see   usb_209.pdf - Table 9-2. Format of Setup Data
//! @{

//! \brief D6...5: Type
//! \brief Defines a standard request
#define USB_STANDARD_REQUEST                0x00

//! \brief Defines a class request
#define USB_CLASS_REQUEST                   0x01

//! \brief Defines a vendor request
#define USB_VENDOR_REQUEST                  0x02

//! \brief Get the type of bmRequestType
#define USB_REQUEST_TYPE(pSetup)            ((pSetup->bmRequestType & 0x60) >> 5)

//! \brief Get the receipient of bmRequestType
#define USB_REQUEST_RECIPIENT(pSetup)       (pSetup->bmRequestType & 0x1F)

//! \brief Recipient is the whole device
#define USB_RECIPIENT_DEVICE                0x00

//! \brief Recipient is an interface
#define USB_RECIPIENT_INTERFACE             0x01

//! \brief Recipient is an endpoint
#define USB_RECIPIENT_ENDPOINT              0x02

//! @}

//! \ingroup usb_std_struc
//! \defgroup ept_desc_macros Endpoint Descriptor - Macros
//! \brief Useful macros when declaring an endpoint descriptor
//! \see S_usb_endpoint_descriptor
//! \see usb_20.pdf - Section 9.6.6 - Table 9.13
//! @{

//! \name bEndpointAddress field
//! @{

//! \brief Returns an endpoint number
#define USB_ENDPOINT_NUMBER(bEndpointAddress)       (bEndpointAddress & 0x0F)

//! \brief Returns an endpoint direction (IN or OUT)
#define USB_ENDPOINT_DIRECTION(bEndpointAddress)    (bEndpointAddress & 0x80)
//! @}
//! @}

//! \ingroup usb_std_req_hlr
//! \defgroup usb_class_codes USB Class Codes
//! These are the class codes approved by the USB-IF organization. They can be
//! used for the bDeviceClass value of a device descriptor, or the
//! bInterfaceClass value of an interface descriptor.
//! \see S_usb_device_descriptor
//! \see S_usb_interface_descriptor
//! \see http://www.usb.org/developers/defined_class
//! @{

//! \brief Indicates that the class information is determined by the interface
//!        descriptor.
#define USB_CLASS_DEVICE                0x00

//! \brief Audio capable devices
#define USB_CLASS_AUDIO                 0x01

//! \brief Communication devices
#define USB_CLASS_COMMUNICATION         0x02

//! \brief Human-interface devices
#define USB_CLASS_HID                   0x03

//! \brief Human-interface devices requiring real-time physical feedback
#define USB_CLASS_PHYSICAL              0x05

//! \brief Still image capture devices
#define USB_CLASS_STILL_IMAGING         0x06

//! \brief Printer devices
#define USB_CLASS_PRINTER               0x07

//! \brief Mass-storage devices
#define USB_CLASS_MASS_STORAGE          0x08

//! \brief Hub devices
#define USB_CLASS_HUB                   0x09

//! \brief Raw-data communication device
#define USB_CLASS_CDC_DATA              0x0A

//! \brief Smartcards devices
#define USB_CLASS_SMARTCARDS            0x0B

//! \brief Protected content devices
#define USB_CLASS_CONTENT_SECURITY      0x0D

//! \brief Video recording devices
#define USB_CLASS_VIDEO                 0x0E

//! \brief Devices that diagnostic devices
#define USB_CLASS_DIAGNOSTIC_DEVICE     0xDC

//! \brief Wireless controller devices
#define USB_CLASS_WIRELESS_CONTROLLER   0xE0

//! \brief Miscellaneous devices
#define USB_CLASS_MISCELLANEOUS         0xEF

//! \brief Application-specific class code
#define USB_CLASS_APPLICATION_SPECIFIC  0xFE

//! \brief Vendor-specific class code
#define USB_CLASS_VENDOR_SPECIFIC       0xFF
//! @}

//! \ingroup usb_std_struc
//! \defgroup dev_desc_const Device Descriptor - Constants
//! Several useful constants when declaring a device descriptor
//! \see S_usb_device_descriptor
//! \see S_usb_device_qualifier_descriptor
//! \see usb_20.pdf - Section 9.6.1 - Table 9.8
//! @{

//! \name USB specification release codes
//! @{

//! bcdUSB field - USB 2.0 specification code
#define USB2_00                     0x0200
#define USB1_10                     0x0110
//! @}

//! \name Vendor IDs
//! @{

//! idVendor - SPECTRA Vendor ID
#define USB_VENDOR_SPECTRA          0x123A
//! @}
//! @}

//! \ingroup usb_std_struc
//! \defgroup cfg_desc_const Configuration Descriptor - Constants
//! Several useful constants when declaring a configuration descriptor
//! \see S_usb_configuration_descriptor
//! \see usb_20.pdf - Section 9.6.3 - Table 9.10
//! @{

//! \name bmAttributes field
//! \brief These are the possible values for the bmAttributes field of a
//!        S_usb_configuration_descriptor.
//! @{

//! \brief Device is bus-powered and does not support remote wakeup
#define USB_CONFIG_BUS_NOWAKEUP    0x80

//! \brief Device is self-powered and does not support remote wakeup
#define USB_CONFIG_SELF_NOWAKEUP   0xC0

//! \brief Device is bus-powered and supports remote wakeup
#define USB_CONFIG_BUS_WAKEUP      0xA0

//! \brief Device is self-powered and supports remote wakeup
#define USB_CONFIG_SELF_WAKEUP     0xE0
//! @}

//! \name Power consumption
//! @{

//! Power consumption macro for the Configuration descriptor
#define USB_POWER_MA(power)        (power/2)
//! @}
//! @}

//! \ingroup usb_std_struc
//! \defgroup str_desc_const String Descriptor - Constants
//! \brief Useful constants when declaring a string descriptor.
//! \see S_usb_string_descriptor
//! \see USB_LANGIDs.pdf
//! @{

//! \name Language IDs
//! \brief These are the supported language IDs as defined by the USB-IF group.
//!        They can be used to specified the languages supported by the string
//!        descriptors of a USB device.
//! @{

//! \brief English (United States)
#define USB_LANGUAGE_ENGLISH_US     0x0409
//! @}
//! @}

//! \ingroup usb_std_struc
//! \defgroup str_desc_macros String Descriptor - Macros
//! \brief Several useful macros when declaring a string descriptor.
//! \see S_usb_string_descriptor
//! @{

//! Converts an ASCII character to its Unicode equivalent
#define USB_UNICODE(a)                      (a), 0x00

//! Calculates the size of a string descriptor given the number of ASCII
//! characters in it
#define USB_STRING_DESCRIPTOR_SIZE(size)    ((size * 2) + 2)
//! @}

//! \ingroup usb_api_methods
//! \defgroup usb_api_ret_val Standard return values
//! \brief Values returned by the API methods.
//! @{

//! \brief Last method has completed successfully
#define USB_STATUS_SUCCESS      0

//! \brief Method was aborted because the recipient (device, endpoint, ...) was
//!        busy
#define USB_STATUS_LOCKED       1

//! \brief Method was aborted because of abnormal status
#define USB_STATUS_ABORTED      2

//! \brief Method was aborted because the endpoint or the device has been reset
#define USB_STATUS_RESET        3

//! @}

// Device State
//! \ingroup S_usb_struc
//! \defgroup S_usb_dev_state USB Device States
//! \brief Constant values used to track which USB state the device is currently
//!        in.
//! @{

//! Attached state
#define USB_STATE_NOTATTACHED                       0

#define USB_STATE_ATTACHED                          (1 << 0)

//! Powered state
#define USB_STATE_POWERED                           (1 << 1)

//! Default state
#define USB_STATE_DEFAULT                           (1 << 2)

//! Address state
#define USB_STATE_ADDRESS                           (1 << 3)

//! Configured state
#define USB_STATE_CONFIGURED                        (1 << 4)

//! Suspended state
#define USB_STATE_SUSPENDED                         (1 << 5)

//! @}

#define USB_ENDPOINT0_MAXPACKETSIZE     8

// Hub constants
/*
 * wPortStatus bit field
 * See USB 2.0 spec Table 11-21
 */
#define USB_PORT_STAT_CONNECTION	0x0001
#define USB_PORT_STAT_ENABLE		0x0002
#define USB_PORT_STAT_SUSPEND		0x0004
#define USB_PORT_STAT_OVERCURRENT	0x0008
#define USB_PORT_STAT_RESET		0x0010
#define USB_PORT_STAT_L1		0x0020
/* bits 6 to 7 are reserved */
#define USB_PORT_STAT_POWER		0x0100
#define USB_PORT_STAT_LOW_SPEED		0x0200
#define USB_PORT_STAT_HIGH_SPEED        0x0400
#define USB_PORT_STAT_TEST              0x0800
#define USB_PORT_STAT_INDICATOR         0x1000
/* bits 13 to 15 are reserved */

/*
 * wPortChange bit field
 * See USB 2.0 spec Table 11-22
 * Bits 0 to 4 shown, bits 5 to 15 are reserved
 */
#define USB_PORT_STAT_C_CONNECTION	0x0001
#define USB_PORT_STAT_C_ENABLE		0x0002
#define USB_PORT_STAT_C_SUSPEND		0x0004
#define USB_PORT_STAT_C_OVERCURRENT	0x0008
#define USB_PORT_STAT_C_RESET		0x0010
#define USB_PORT_STAT_C_L1		0x0020

//------------------------------------------------------------------------------
//      Structures
//------------------------------------------------------------------------------

//#pragma pack(1)
// USB standard structures
//-------------------------
//! \ingroup usb_std_struc
//! \brief This structure represents a standard SETUP request
//! \see usb_20.pdf - Section 9.3 - Table 9.2
typedef struct {


    unsigned char   bmRequestType:8;    //!< Characteristics of the request
    unsigned char   bRequest:8;         //!< Particular request
    unsigned short  wValue:16;          //!< Request-specific parameter
    unsigned short  wIndex:16;          //!< Request-specific parameter
    unsigned short  wLength:16;         //!< Length of data for the data phase

} S_usb_request;

#pragma pack(1)
//! \ingroup usb_std_struc
//! \brief This descriptor structure is used to provide information on
//!        various parameters of the device
//!
//! Usage example:
//! \include S_usb_device_descriptor_example.c
//! \see usb_20.pdf - Section 9.6.1
typedef struct {

   unsigned char  bLength;              //!< Size of this descriptor in bytes
   unsigned char  bDescriptorType;      //!< DEVICE descriptor type
   unsigned short bcdUSB;               //!< USB specification release number
   unsigned char  bDeviceClass;         //!< Class code
   unsigned char  bDeviceSubClass;      //!< Subclass code
   unsigned char  bDeviceProtocol;      //!< Protocol code
   unsigned char  bMaxPacketSize0;      //!< Control endpoint 0 max. packet size
   unsigned short idVendor;             //!< Vendor ID
   unsigned short idProduct;            //!< Product ID
   unsigned short bcdDevice;            //!< Device release number
   unsigned char  iManufacturer;        //!< Index of manu. string descriptor
   unsigned char  iProduct;             //!< Index of prod. string descriptor
   unsigned char  iSerialNumber;        //!< Index of S.N.  string descriptor
   unsigned char  bNumConfigurations;   //!< Number of possible configurations
}  S_usb_device_descriptor;

#pragma pack(1)
//! \ingroup usb_std_struc
//! \brief This is the standard configuration descriptor structure. It is used
//!        to report the current configuration of the device.
//!
//! Usage example:
//! \include S_usb_configuration_descriptor_example.c
//! \see usb_20.pdf - Section 9.6.3
typedef struct {

   unsigned char  bLength;              //!< Size of this descriptor in bytes
   unsigned char  bDescriptorType;      //!< CONFIGURATION descriptor type
   unsigned short wTotalLength;         //!< Total length of data returned
                                        //!< for this configuration
   unsigned char  bNumInterfaces;       //!< Number of interfaces for this
                                        //!< configuration
   unsigned char  bConfigurationValue;  //!< Value to use as an argument for
                                        //!< the Set Configuration request to
                                        //!< select this configuration
   unsigned char  iConfiguration;       //!< Index of string descriptor
                                        //!< describing this configuration
   unsigned char  bmAttibutes;          //!< Configuration characteristics
   unsigned char  bMaxPower;            //!< Maximum power consumption of the
                                        //!< device
} S_usb_configuration_descriptor;

#pragma pack(1)
//! \ingroup usb_std_struc
//! \brief Standard interface descriptor. Used to describe a specific interface
//!        of a configuration.
//!
//! Usage example:
//! \include S_usb_interface_descriptor_example.c
//! \see usb_20.pdf - Section 9.6.5
typedef struct {

   unsigned char bLength;               //!< Size of this descriptor in bytes
   unsigned char bDescriptorType;       //!< INTERFACE descriptor type
   unsigned char bInterfaceNumber;      //!< Number of this interface
   unsigned char bAlternateSetting;     //!< Value used to select this alternate
                                        //!< setting
   unsigned char bNumEndpoints;         //!< Number of endpoints used by this
                                        //!< interface (excluding endpoint zero)
   unsigned char bInterfaceClass;       //!< Class code
   unsigned char bInterfaceSubClass;    //!< Sub-class
   unsigned char bInterfaceProtocol;    //!< Protocol code
   unsigned char iInterface;            //!< Index of string descriptor
                                        //!< describing this interface
} S_usb_interface_descriptor;

#pragma pack(1)
//! \ingroup usb_std_struc
//! \brief Standard interface association descriptor. Used to describe a
//!         specific interface of a configuration.
//!
//! Usage example:
//! \see InterfaceAssociationDescriptor_ecn.pdf - Section 9.X.Y
typedef struct {

   unsigned char bLength;               //!< Size of this descriptor in bytes
   unsigned char bDescriptorType;       //!< INTERFACE descriptor type
   unsigned char bFirstInterface;      	//!< Interface number of the first interface
					//!<  that isassociated with this function.
   unsigned char bInterfaceCount;     	//!< Number of contiguous interfaces that are
                                        //!< associated with this function.
   unsigned char bFunctionClass;       	//!< Class code
   unsigned char bFunctionSubClass;    	//!< Sub-class
   unsigned char bFunctionProtocol;    	//!< Protocol code
   unsigned char iFunction;            	//!< Index of string descriptor
                                        //!< describing this function
} S_usb_interface_assoc_descriptor;

#pragma pack(1)
//! \ingroup usb_std_struc
//! \brief This structure is the standard endpoint descriptor. It contains
//!        the necessary information for the host to determine the bandwidth
//!        required by the endpoint.
//!
//! Usage example:
//! \include S_usb_endpoint_descriptor_example.c
//! \see usb_20.pdf - Section 9.6.6
typedef struct {

   unsigned char  bLength;              //!< Size of this descriptor in bytes
   unsigned char  bDescriptorType;      //!< ENDPOINT descriptor type
   unsigned char  bEndpointAddress;     //!< Address of the endpoint on the USB
                                        //!< device described by this descriptor
   unsigned char  bmAttributes;         //!< Endpoint attributes when configured
   unsigned short wMaxPacketSize;       //!< Maximum packet size this endpoint
                                        //!< is capable of sending or receiving
   unsigned char  bInterval;            //!< Interval for polling endpoint for
                                        //!< data transfers
} S_usb_endpoint_descriptor;

#pragma pack(1)

// bmAttributes
#define USB_ENDPOINT_XFERTYPE_MASK  3

//! \ingroup usb_std_struc
//! \brief The device qualifier structure provide information on a high-speed
//!        capable device if the device was operating at the other speed.
//!
//! Usage example:
//! \include S_usb_device_qualifier_descriptor_example.c
//! \see usb_20.pdf - Section 9.6.2
typedef struct {

   unsigned char  bLength;              //!< Size of this descriptor in bytes
   unsigned char  bDescriptorType;      //!< DEVICE_QUALIFIER descriptor type
   unsigned short bscUSB;               //!< USB specification release number
   unsigned char  bDeviceClass;         //!< Class code
   unsigned char  bDeviceSubClass;      //!< Sub-class code
   unsigned char  bDeviceProtocol;      //!< Protocol code
   unsigned char  bMaxPacketSize0;      //!< Control endpoint 0 max. packet size
   unsigned char  bNumConfigurations;   //!< Number of possible configurations
   unsigned char  bReserved;            //!< Reserved for future use, must be 0

} S_usb_device_qualifier_descriptor;

//#pragma pack(1)
//! \ingroup usb_std_struc
//! \brief The S_usb_language_id structure represents the string descriptor
//!        zero, used to specify the languages supported by the device. This
//!        structure only define one language ID.
//!
//! Usage example:
//! \include S_usb_language_id_example.c
//! \see usb_20.pdf - Section 9.6.7 - Table 9.15
typedef struct {

   unsigned char  bLength;               //!< Size of this descriptor in bytes
   unsigned char  bDescriptorType;       //!< STRING descriptor type
   unsigned short wLANGID;               //!< LANGID code zero

} S_usb_language_id;

//#pragma pack(1)
typedef struct _USB_STRING_DESCRIPTOR
{
    unsigned char bLength;
    unsigned char bDescriptorType;
    unsigned char bString[1];
} S_usb_string_descriptor;

#pragma pack()
//-----------------------------------------------------------------------------
// USB Device related struct
//-----------------------------------------------------------------------------
struct S_usbh_driver;
struct S_USBH_Device;

typedef struct S_USBH_Endpoint
{
    S_usb_endpoint_descriptor desc;
    void *hc_ed;        // hc's endpoint descriptor
    struct S_USBH_Device *dev;
    unsigned char *extra;   // Extra descriptors
    unsigned short interval;
    unsigned short rfu;
    T_BUF *list;
    int extralen;
    int enabled;
} T_USBH_Endpoint;

#define MAX_USBINTERFACES       8
#define USB_MAXIADS             MAX_USBINTERFACES/2

typedef struct S_usb_host_interface
{
    S_usb_interface_descriptor  desc;

    // endpoint array
    T_USBH_Endpoint *endpoint;
    char *string;       /* iInterface string, if present */
    unsigned char *extra;   /* Extra descriptors */
    int extralen;
} T_usb_host_interface;

enum usb_interface_condition {
    USB_INTERFACE_UNBOUND = 0,
    USB_INTERFACE_BINDING,
    USB_INTERFACE_BOUND,
    USB_INTERFACE_UNBINDING,
};

typedef struct S_usb_interface
{
    struct S_Device dev;
    T_usb_host_interface *altsetting;
    // the currently active alternate setting
    T_usb_host_interface *cur_altsetting;
    unsigned int num_altsetting;    //number of alternate settings
    S_usb_interface_assoc_descriptor *intf_assoc;

    enum usb_interface_condition condition;     /* state of binding */
    unsigned int is_active:1;       /* the interface is not suspended */
    unsigned int needs_remote_wakeup:1; /* driver requires remote wakeup */
    unsigned int needs_altsetting0:1;   /* switch to altsetting 0 is pending */
    unsigned int needs_binding:1;   /* needs delayed unbind/rebind */

    int pm_usage_cnt;       /* usage counter for autosuspend */
} T_usb_interface;

/**
 * usb_interface_claimed - returns true iff an interface is claimed
 * @iface: the interface being checked
 *
 * Returns true (nonzero) iff the interface is claimed, else false (zero).
 * Callers must own the driver model's usb bus readlock.  So driver
 * probe() entries don't need extra locking, but other call contexts
 * may need to explicitly claim that lock.
 *
 */
#define usb_interface_claimed(iface)    ((iface)->dev.driver != NULL)

/**
 * struct usb_interface_cache - long-term representation of a device interface
 * @num_altsetting: number of altsettings defined.
 * @ref: reference counter.
 * @altsetting: variable-length array of interface structures, one for
 *  each alternate setting that may be selected.  Each one includes a
 *  set of endpoint configurations.  They will be in no particular order.
 *
 * These structures persist for the lifetime of a usb_device, unlike
 * struct usb_interface (which persists only as long as its configuration
 * is installed).  The altsetting arrays can be accessed through these
 * structures at any time, permitting comparison of configurations and
 * providing support for the /proc/bus/usb/devices pseudo-file.
 */
struct usb_interface_cache {
    unsigned num_altsetting;    /* number of alternate settings */
    int ref;        /* reference counter */

    /* variable-length array of alternate settings for this interface,
     * stored in no particular order */
    struct S_usb_host_interface altsetting[0];
};

typedef struct S_USBH_Configuration
{
    S_usb_configuration_descriptor desc;
    // List of any Interface Association Descriptors in this configuration.
    S_usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
    struct S_usb_interface *uif[MAX_USBINTERFACES];
    // Interface information available even when this is not the active configuration
    struct usb_interface_cache *intf_cache[MAX_USBINTERFACES];
    unsigned char *extra;   /* Extra descriptors */
    int extralen;
} T_USBH_Configuration;

#define USB_MAXCHILDREN 1
#define USB_MAX_CONFIG  4

typedef struct S_USBH_Device
{
    struct S_Device dev;
    S_usb_device_descriptor desc;
    T_USBH_Configuration *config;    // config array
    T_USBH_Configuration *actconfig; // active config
    unsigned char utbnum;
    char devnum;    // usb address
    char state;
    unsigned char maxchild;
    struct S_USBH_Device *children[USB_MAXCHILDREN];
    unsigned short bus_mA;
    unsigned char portnum;
    unsigned char level;
    unsigned int toggle[2];    //one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints
    char product[256];
    char manufacturer[256];
    char serial[256];
    T_USBH_Endpoint ep0;
    T_USBH_Endpoint *ep_in[16];
    T_USBH_Endpoint *ep_out[16];
    unsigned char *rawdescriptors[USB_MAX_CONFIG];
    unsigned int speed:2;
    unsigned int canWakeup;
    unsigned int canSubmit:1;
    unsigned int have_langid:1;
    unsigned int discon_suspended:1;
    unsigned int autosuspend:1;
    unsigned int auto_pm:1;
    unsigned int do_remote_wakeup:1;
    unsigned int reset_resume:1;
    unsigned int autosuspend_disabled:1;
    unsigned int autoresume_disabled:1;
    unsigned int skip_sys_resume:1;
    int suspend_pending;
    int string_langid;
    int pm_usage_cnt;       /* usage counter for autosuspend */
    unsigned int last_busy;
    // for setup process
    T_BUF *setup_message;
    unsigned int setup_timeout;
    char setup_resend_count;
    unsigned char setup_desc_type;
    unsigned char setup_request;
    unsigned char config_state;
    int setup_cfg_count;
} T_USBH_Device;

typedef void (*complete_fn)(T_BUF *buf);

typedef struct S_USB_TransferBlock
{
    T_USBH_Device *dev;
    T_USBH_Endpoint *ep;
    unsigned int pipe;
    complete_fn complete;
    unsigned int flags;
    int status;
    short length;
    short transfered;
    unsigned short hc_blk_count;        // no. of block in HC
    unsigned short hc_xfer_count;       // no. of block transfered
    int interval;
    int unlinked;
    S_usb_request *setup_packet;
    unsigned char *data;
    void *hc_blk[4];                    // block list
    T_BUF *next;
    void *context;
    unsigned int rfu[6];                // makes total size of struct 96 bytes (must 32 bytes align)
} T_USB_TransferBlock;

// S_USB_TransferBlock flags
#define UTB_SHORT_NOT_OK    0x0001  /* report short reads as errors */
#define UTB_ISO_ASAP        0x0002  /* iso-only, urb->start_frame ignored */
#define UTB_NO_TRANSFER_DMA_MAP 0x0004  /* urb->transfer_dma valid on submit */
#define UTB_NO_SETUP_DMA_MAP    0x0008  /* urb->setup_dma valid on submit */
#define UTB_NO_FSBR         0x0020  /* UHCI-specific */
#define UTB_ZERO_PACKET     0x0040  /* Finish bulk OUT with short packet */
#define UTB_NO_INTERRUPT    0x0080  /* HINT: no non-error interrupt needed */
#define UTB_FREE_BUFFER     0x0100  /* Free transfer buffer with the URB */
#define UTB_DIR_IN          0x0200  /* Transfer from device to host */
#define UTB_DIR_OUT         0
#define UTB_DIR_MASK        UTB_DIR_IN

// pipe: bit7 Dir IN, bit8-14 device addr, bit15-18 endpoint, bit30-31 type
#define USB_ENDPOINT_DIR_MASK   0x80
#define USB_DIR_OUT         0
#define USB_DIR_IN          0x80
#define usb_pipein(pipe)    ((pipe) & USB_DIR_IN)
#define usb_pipeout(pipe)   (!usb_pipein(pipe))
#define usb_pipedevice(pipe)    (((pipe) >> 8) & 0x7f)
#define usb_pipeendpoint(pipe)  (((pipe) >> 15) & 0xf)
#define usb_pipetype(pipe)  (((pipe) >> 30) & 3)
#define usb_pipeisoc(pipe)  (usb_pipetype((pipe)) == ENDPOINT_TYPE_ISOCHRONOUS)
#define usb_pipeint(pipe)   (usb_pipetype((pipe)) == ENDPOINT_TYPE_INTERRUPT)
#define usb_pipecontrol(pipe)   (usb_pipetype((pipe)) == ENDPOINT_TYPE_CONTROL)
#define usb_pipebulk(pipe)  (usb_pipetype((pipe)) == ENDPOINT_TYPE_BULK)

/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
#define usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << (ep)))
#define usb_settoggle(dev, ep, out, bit) \
        ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \
         ((bit) << (ep)))

/* Create various pipes... */
#define __create_pipe(dev,endpoint) \
    (((dev)->devnum << 8) | ((endpoint) << 15))
#define usb_sndctrlpipe(dev,endpoint)   \
    ((ENDPOINT_TYPE_CONTROL << 30) | __create_pipe(dev, endpoint))
#define usb_rcvctrlpipe(dev,endpoint)   \
    ((ENDPOINT_TYPE_CONTROL << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndisocpipe(dev,endpoint)   \
    ((ENDPOINT_TYPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint))
#define usb_rcvisocpipe(dev,endpoint)   \
    ((ENDPOINT_TYPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndbulkpipe(dev,endpoint)   \
    ((ENDPOINT_TYPE_BULK << 30) | __create_pipe(dev, endpoint))
#define usb_rcvbulkpipe(dev,endpoint)   \
    ((ENDPOINT_TYPE_BULK << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndintpipe(dev,endpoint)    \
    ((ENDPOINT_TYPE_INTERRUPT << 30) | __create_pipe(dev, endpoint))
#define usb_rcvintpipe(dev,endpoint)    \
    ((ENDPOINT_TYPE_INTERRUPT << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)

#define usb_endpoint_dir_out(epd) (((epd)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
#define usb_endpoint_out(ep_dir)    (!((ep_dir) & USB_DIR_IN))
#define usb_endpoint_dir_in(epd)  (((epd)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)

#define usb_endpoint_xfer_control(epd)  (((epd)->bmAttributes & 3) == ENDPOINT_TYPE_CONTROL)
#define usb_endpoint_xfer_isoc(epd)     (((epd)->bmAttributes & 3) == ENDPOINT_TYPE_ISOCHRONOUS)
#define usb_endpoint_xfer_bulk(epd)     (((epd)->bmAttributes & 3) == ENDPOINT_TYPE_BULK)
#define usb_endpoint_xfer_int(epd)      (((epd)->bmAttributes & 3) == ENDPOINT_TYPE_INTERRUPT)
#define usb_endpoint_num(epd)           ((epd)->bEndpointAddress & 0xf)

/*! \brief usb device id is used by usb host to match driver
 * usb host can find the driver by id or device type. The searching method is
 * depends on the match_flags.
 */
struct usb_device_id
{
    unsigned short vendor_id;           // match vendor id
    unsigned short product_id;          // match product id
    unsigned short device_ver_hi;       // match within the version range (inclusive)
    unsigned short device_ver_lo;
    unsigned char dev_class;            // match device class
    unsigned char dev_subclass;         // match device subclass
    unsigned char dev_protocol;         // match device protocol
    unsigned char if_class;             // match interface class
    unsigned char if_subclass;          // match interface subclass
    unsigned char if_protocol;          // match interface protocol
    unsigned short flags;
};

// flags defines
#define USB_MATCH_VENDOR_ID     0x0001
#define USB_MATCH_PRODUCT_ID    0x0002
#define USB_MATCH_DEV_VER_LO    0x0004
#define USB_MATCH_DEV_VER_HI    0x0008
#define USB_MATCH_DEV_CLASS     0x0010
#define USB_MATCH_DEV_SUBCLASS  0x0020
#define USB_MATCH_DEV_PROTOCOL  0x0040
#define USB_MATCH_IF_CLASS      0x0100
#define USB_MATCH_IF_SUBCLASS   0x0200
#define USB_MATCH_IF_PROTOCOL   0x0400

/**
 * usb interface driver
 */
typedef struct S_usbh_driver
{
    struct S_Driver drv;
    const struct usb_device_id *usb_id_table;
    int (*pre_reset)(T_usb_interface *intf);
    int (*post_reset)(T_usb_interface *intf, int result);
    int (*reset_resume)(T_usb_interface *intf);
} T_usbh_driver;

// usb device and interface driver attribute
#define DA_DEVICE_DRIVER        0x01000000
#define DA_AUTOSUSPEND          0x02000000
#define DA_SOFT_UNBIND          0x04000000

#endif
